It may seem odd that in a framework that embraces "convention-over-configuration" that we tackle this topic now, but since what configuration there is typically a one off, it is best to get it out the way.With Grails' default settings you can actually develop and application without doing any configuration whatsoever. Grails ships with an embedded container and in-memory HSQLDB meaning there isn't even a database to set-up.However, typically you want to set-up a real database at some point and the way you do that is described in the following section.For general configuration Grails provides a file called grails-app/conf/Config.groovy
. This file uses Groovy's ConfigSlurper which is very similar to Java properties files except it is pure Groovy hence you can re-use variables and use proper Java types!You can add your own configuration in here, for example:Then later in your application you can access these settings in one of two ways. The most common is via the GrailsApplication object, which is available as a variable in controllers and tag libraries:assert "world" == grailsApplication.config.foo.bar.hello
The other way involves getting a reference to the ConfigurationHolder class that holds a reference to the configuration object:import org.codehaus.groovy.grails.commons.*
…
def config = ConfigurationHolder.config
assert "world" == config.foo.bar.hello
Grails also provides the following configuration options:
grails.config.locations
- The location of properties files or addition Grails Config files that should be merged with main configuration
grails.enable.native2ascii
- Set this to false if you do not require native2ascii conversion of Grails i18n properties files
grails.views.default.codec
- Sets the default encoding regime for GSPs - can be one of 'none', 'html', or 'base64' (default: 'none'). To reduce risk of XSS attacks, set this to 'html'.
grails.views.gsp.encoding
- The file encoding used for GSP source files (default is 'utf-8')
grails.mime.file.extensions
- Whether to use the file extension to dictate the mime type in Content Negotiation
grails.mime.types
- A map of supported mime types used for Content Negotiation
grails.serverURL
- A string specifying the server URL portion of absolute links, including server name e.g. grails.serverURL="http://my.yourportal.com". See createLink.
War generation
grails.war.destFile
- Sets the location where the war command should place the generated WAR file
grails.war.dependencies
- A closure containing Ant builder syntax or a list of JAR filenames. Allows you to customise what libaries are included in the WAR file.
grails.war.java5.dependencies
- A list of the JARs that should be included in the WAR file for JDK 1.5 and above.
grails.war.copyToWebApp
- A closure containing Ant builder syntax that is legal inside an Ant copy, for example "fileset()". Allows you to control what gets included in the WAR file from the "web-app" directory.
grails.war.resources
- A closure containing Ant builder syntax. Allows the application to do any other pre-warring stuff it needs to.
For more information on using these options, see the section on deployment
Logging Basics
Grails uses its common configuration mechanism to configure the underlying Log4j log system. To configure logging you must modify the file Config.groovy
located in the grails-app/conf
directory. This single Config.groovy
file allows you to specify separate logging configurations for development
, test
, and production
environments. Grails processes the Config.groovy
file and generates the appropriate log4j.properties
file in the web-app/WEB-INF/classes
directory.An example of a typical Log4j configuration in Grails is as follows:log4j {
appender.stdout = "org.apache.log4j.ConsoleAppender"
appender.'stdout.layout'="org.apache.log4j.PatternLayout"
rootLogger="error,stdout"
logger {
grails="info,stdout"
org {
grails.spring="info,stdout"
codehaus.groovy.grails.web="info,stdout"
codehaus.groovy.grails.commons="info,stdout"
…
}
}
}
If you prefer to use standard Log4j properties file style configuration you can use a Groovy multiline String instead:log4j = '''
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# ...remaining configuration
'''
Some useful loggers include:
org.codehaus.groovy.grails.commons
- Core artefact information such as class loading etc.
org.codehaus.groovy.grails.web
- Grails web request processing
org.codehaus.groovy.grails.web.mapping
- URL mapping debugging
org.codehaus.groovy.grails.plugins
- Log plugin activity
org.springframework
- See what Spring is doing
org.hibernate
- See what Hibernate is doing
Full stacktraces
When exceptions occur, there can be an awful lot of noise in the stacktrace from Java and Groovy internals. Grails filters these typically irrelevant details and restricts traces to non-core Grails/Groovy class packages.When this happens, the full trace is always written to the StackTrace
logger. This logs to a file called stacktrace.log
- but you can change this in your Config.groovy
to do anything you like. For example if you prefer full stack traces to go to standard out you can change the line:StackTrace="error,stacktraceLog"
To:StackTrace="error,stdout"
You can completely disable stacktrace filtering by setting the grails.full.stacktrace
VM property to true
:grails -Dgrails.full.stacktrace=true run-app
Logging by Convention
All application artefacts have a dynamically added log
property. This includes domain classes, controllers, tag libraries and so on. Below is an example of its usage:def foo = "bar"
log.debug "The value of foo is $foo"
Logs are named using the convention grails.app.<artefactType>.ClassName
. Below is an example of how to configure logs for different Grails artefacts:# Set level for all application artefacts
log4j.logger.grails.app="info, stdout"# Set for a specific controller
log4j.logger.grails.app.controller.YourController="debug, stdout"# Set for a specific domain class
log4j.logger.grails.app.domain.Book="debug, stdout"# Set for a specific taglib
log4j.logger.grails.app.tagLib.FancyAjax="debug, stdout"# Set for all taglibs
log4j.logger.grails.app.tagLib="info, stdout"
The artefacts names are dictated by convention, some of the common ones are listed below:
bootstrap
- For bootstrap classes
dataSource
- For data sources
tagLib
- For tag libraries
service
- For service classes
controller
- For controllers
domain
- For domain entities
Per Environment Configuration
Grails supports the concept of per environment configuration. Both the Config.groovy
file and the DataSource.groovy
file within the grails-app/conf
directory can take advantage of per environment configuration using the syntax provided by ConfigSlurper As an example consider the following default DataSource
definition provided by Grails:dataSource {
pooled = false
driverClassName = "org.hsqldb.jdbcDriver"
username = "sa"
password = ""
}
environments {
development {
dataSource {
dbCreate = "create-drop" // one of 'create', 'createeate-drop','update'
url = "jdbc:hsqldb:mem:devDB"
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:hsqldb:mem:testDb"
}
}
production {
dataSource {
dbCreate = "update"
url = "jdbc:hsqldb:file:prodDb;shutdown=true"
}
}
}
Notice how the common configuration is provided at the top level and then an environments
block specifies per environment settings for the dbCreate
and url
properties of the DataSource
. This syntax can also be used within Config.groovy
.Packaging and Running for Different Environments
Grails' command line has built in capabilities to execute any command within the context of a specific environment. The format is:grails [environment] [command name]
In addition, there are 3 preset environments known to Grails: dev
, prod
, and test
for development
, production
and test
. For example to create a WAR for the test
environment you could do:If you have other environments that you need to target you can pass a grails.env
variable to any command:grails -Dgrails.env=UAT run-app
Programmatic Environment Detection
Within your code, such as in a Gant script or a bootstrap class you can detect the environment using the GrailsUtil class:import grails.util.GrailsUtil...switch(GrailsUtil.environment) {
case "development":
configureForDevelopment()
break
case "production":
configureForProduction()
break
}
Since Grails is built on Java technology to set-up a data source requires some knowledge of JDBC (the technology that doesn't stand for Java Database Connectivity).Essentially, if you are using another database other than HSQLDB you need to have a JDBC driver. For example for MySQL you would need Connector/JDrivers typically come in the form of a JAR archive. Drop the JAR into your projects lib
directory.Once you have the JAR in place you need to get familiar Grails' DataSource descriptor file located at grails-app/conf/DataSource.groovy
. This file contains the dataSource definition which includes the following settings:
driverClassName
- The class name of the JDBC driver
username
- The username used to establish a JDBC connection
password
- The password used to establish a JDBC connection
url
- The JDBC URL of the database
dbCreate
- Whether to auto-generate the database from the domain model or not
pooled
- Whether to use a pool of connections (defaults to true)
logSql
- Enable SQL logging
dialect
- A String or Class that represents the Hibernate dialect used to communicate with the database. See the org.hibernate.dialect package for available dialects.
A typical configuration for MySQL may be something like:dataSource {
pooled = true
dbCreate = "update"
url = "jdbc:mysql://localhost/yourDB"
driverClassName = "com.mysql.jdbc.Driver"
username = "yourUser"
password = "yourPassword"
}
When configuring the DataSource do not include the type or the def keyword before any of the configuration settings as Groovy will treat these as local variable definitions and they will not be processed. For example the following is invalid:
dataSource {
boolean pooled = true // type declaration results in local variable
…
}
The previous example configuration assumes you want the same config for all environments: production, test, development etc.Grails' DataSource definition is "environment aware", however, so you can do:dataSource {
// common settings here
}
environments {
production {
dataSource {
url = "jdbc:mysql://liveip.com/liveDb"
}
}
}
Since many Java EE containers typically supply DataSource
instances via the Java Naming and Directory Interface (JNDI). Sometimes you are required to look-up a DataSource
via JNDI.Grails supports the definition of JNDI data sources as follows:dataSource {
jndiName = "java:comp/env/myDataSource"
}
The format on the JNDI name may vary from container to container, but the way you define the DataSource
remains the same.The dbCreate
property of the DataSource
definition is important as it dictates what Grails should do at runtime with regards to automatically generating the database tables from GORM classes. The options are:
create-drop
- Drop and re-create the database when Grails is run
create
- Create the database if it doesn't exist, but don't modify it if it does. Deletes existing data.
update
- Create the database if it doesn't exist, and modify it if it does exist
Both create-drop
and create
will destroy all existing data hence use with caution!
In development mode dbCreate
is by default set to "create-drop":dataSource {
dbCreate = "create-drop" // one of 'create', 'create-drop','update'
}
What this does is automatically drop and re-create the database tables on each restart of the application. Obviously this may not be what you want in production.
Although Grails does not currently support Rails-style Migrations out of the box, there are currently two plug-ins that provide similar capabilities to Grails: The LiquiBase plug-in and the DbMigrate plug-in both of which are available via the grails list-plugins
command
The default configuration file Config.groovy
in grails-app/conf
is fine in the majority of cases, but there may be circumstances where you want to maintain the configuration in a file outside the main application structure. For example if you are deploying to a WAR some administrators prefer the configuration of the application to be externalized to avoid having to re-package the WAR due to a change of configuration.In order to support deployment scenarios such as these the configuration can be externalized. To do so you need to point Grails at the locations of the configuration files Grails should be using by adding a grails.config.locations
setting in Config.groovy
:grails.config.locations = [ "classpath:${appName}-config.properties",
"classpath:${appName}-config.groovy",
"file:${userHome}/.grails/${appName}-config.properties",
"file:${userHome}/.grails/${appName}-config.groovy"]
In the above example we're loading configuration files (both Java properties files and ConfigSlurper configurations) from different places on the classpath and files located in USER_HOME
.Ultimately all configuration files get merged into the config
property of the GrailsApplication object and are hence obtainable from there.
Grails also supports the concept of property place holders and property override configurers as defined in Spring For more information on these see the section on Grails and Spring
Versioning Basics
Grails has built in support for application versioning. When you first create an application with the create-app command the version of the application is set to 0.1
. The version is stored in the application meta data file called application.properties
in the root of the project.To change the version of your application you can run the set-version command:The version is used in various commands including the war command which will append the application version to the end of the created WAR file.Detecting Versions at Runtime
You can detect the application version using Grails' support for application metadata using the GrailsApplication class. For example within controllers there is an implicit grailsApplication variable that can be used:def version = grailsApplication.metadata['app.version']
If it is the version of Grails you need you can use:def grailsVersion = grailsApplication.metadata['app.grails.version']
or the GrailsUtil
class:import grails.util.*
def grailsVersion = GrailsUtil.grailsVersion